"""
画布显示组件
"""

import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
import numpy as np
from typing import TYPE_CHECKING, Optional

try:
    from tkinterdnd2 import DND_FILES
    DRAG_DROP_AVAILABLE = True
except ImportError:
    DRAG_DROP_AVAILABLE = False

if TYPE_CHECKING:
    from ..main_window import MainWindow


class CanvasDisplayMixin:
    """画布显示 Mixin 类"""
    
    def _create_main_content(self: 'MainWindow'):
        """创建主内容区域"""
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 左侧：原始图片
        left_frame = ttk.LabelFrame(main_frame, text="原始图片（点击选择对象）", padding=5)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
        
        canvas_bg = self.config.get('ui.canvas_bg_color', '#2b2b2b')
        self.original_canvas = tk.Canvas(left_frame, bg=canvas_bg, cursor="crosshair", highlightthickness=0)
        self.original_canvas.pack(fill=tk.BOTH, expand=True)
        
        # 绑定鼠标事件
        self.original_canvas.bind("<Button-1>", self.on_canvas_click)
        self.original_canvas.bind("<B1-Motion>", self.on_canvas_drag)
        self.original_canvas.bind("<ButtonRelease-1>", self.on_canvas_release)
        self.original_canvas.bind("<Button-3>", self.on_right_click)
        # 绑定窗口大小改变事件
        self.original_canvas.bind("<Configure>", self.on_original_canvas_resize)
        
        # 保存左侧框架引用（用于拖拽提示）
        self.left_frame = left_frame
        
        # 右侧：分割结果
        right_frame = ttk.LabelFrame(main_frame, text="分割结果", padding=5)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        self.result_canvas = tk.Canvas(right_frame, bg=canvas_bg, highlightthickness=0)
        self.result_canvas.pack(fill=tk.BOTH, expand=True)
        # 绑定窗口大小改变事件
        self.result_canvas.bind("<Configure>", self.on_result_canvas_resize)
    
    def canvas_to_image_coords(self: 'MainWindow', canvas_x, canvas_y):
        """将 canvas 坐标转换为图片坐标"""
        img_x = round((canvas_x - self.original_offset_x) / self.original_scale)
        img_y = round((canvas_y - self.original_offset_y) / self.original_scale)
        return img_x, img_y
    
    def display_original_image(self: 'MainWindow'):
        """显示原始图片"""
        if self.image is None:
            return
        
        # 获取 canvas 尺寸
        self.original_canvas.update()
        canvas_width = self.original_canvas.winfo_width()
        canvas_height = self.original_canvas.winfo_height()
        
        if canvas_width <= 1 or canvas_height <= 1:
            return
        
        # 计算缩放比例
        img_height, img_width = self.image.shape[:2]
        fit_ratio = self.config.get('ui.canvas_fit_ratio', 0.95)
        scale = min(canvas_width / img_width, canvas_height / img_height) * fit_ratio
        
        self.original_scale = scale
        self.original_offset_x = (canvas_width - img_width * scale) / 2
        self.original_offset_y = (canvas_height - img_height * scale) / 2
        
        # 调整图片大小
        new_width = int(img_width * scale)
        new_height = int(img_height * scale)
        
        import cv2
        resized = cv2.resize(self.image, (new_width, new_height))
        
        # 转换为 PIL Image
        pil_image = Image.fromarray(resized)
        photo = ImageTk.PhotoImage(pil_image)
        
        # 显示在 canvas
        self.original_canvas.delete("all")
        self.original_canvas.create_image(
            self.original_offset_x, self.original_offset_y,
            anchor=tk.NW, image=photo, tags="image"
        )
        self.original_canvas.image = photo
        self.original_image_photo = photo
    
    def display_original_image_custom(self: 'MainWindow', image: np.ndarray):
        """
        显示自定义图片到左侧画布（如去背景图）
        
        Args:
            image: 要显示的图片 (RGB格式)
        """
        if image is None:
            return
        
        # 获取 canvas 尺寸
        self.original_canvas.update()
        canvas_width = self.original_canvas.winfo_width()
        canvas_height = self.original_canvas.winfo_height()
        
        if canvas_width <= 1 or canvas_height <= 1:
            return
        
        # 计算缩放比例
        img_height, img_width = image.shape[:2]
        fit_ratio = self.config.get('ui.canvas_fit_ratio', 0.95)
        scale = min(canvas_width / img_width, canvas_height / img_height) * fit_ratio
        
        self.original_scale = scale
        self.original_offset_x = (canvas_width - img_width * scale) / 2
        self.original_offset_y = (canvas_height - img_height * scale) / 2
        
        # 调整图片大小
        new_width = int(img_width * scale)
        new_height = int(img_height * scale)
        
        import cv2
        resized = cv2.resize(image, (new_width, new_height))
        
        # 转换为 PIL Image
        pil_image = Image.fromarray(resized)
        photo = ImageTk.PhotoImage(pil_image)
        
        # 显示在 canvas
        self.original_canvas.delete("all")
        self.original_canvas.create_image(
            self.original_offset_x, self.original_offset_y,
            anchor=tk.NW, image=photo, tags="image"
        )
        self.original_canvas.image = photo
        self.original_image_photo = photo
    
    def display_image(self: 'MainWindow', image, canvas):
        """在 Canvas 上显示图片"""
        if image is None:
            return
        
        # 获取 canvas 尺寸
        canvas.update()
        canvas_width = canvas.winfo_width()
        canvas_height = canvas.winfo_height()
        
        if canvas_width <= 1 or canvas_height <= 1:
            return
        
        # 计算缩放比例
        img_height, img_width = image.shape[:2]
        fit_ratio = self.config.get('ui.canvas_fit_ratio', 0.95)
        scale = min(canvas_width / img_width, canvas_height / img_height) * fit_ratio
        
        offset_x = (canvas_width - img_width * scale) / 2
        offset_y = (canvas_height - img_height * scale) / 2
        
        new_width = int(img_width * scale)
        new_height = int(img_height * scale)
        
        import cv2
        resized = cv2.resize(image, (new_width, new_height))
        
        # 转换为 PIL Image
        pil_image = Image.fromarray(resized)
        photo = ImageTk.PhotoImage(pil_image)
        
        # 显示在 canvas
        canvas.delete("all")
        canvas.create_image(offset_x, offset_y, anchor=tk.NW, image=photo, tags="image")
        canvas.image = photo
        
        if canvas == self.result_canvas:
            self.result_image_photo = photo
    
    def display_depth_map(self: 'MainWindow'):
        """显示景深图（彩色可视化）"""
        if self.depth_map is None:
            return
        
        try:
            # 获取彩色可视化
            colored_depth = self.depth_processor.get_depth_visualization()
            
            if colored_depth is None:
                # 如果可视化失败，使用灰度图
                colored_depth = np.stack([self.depth_map] * 3, axis=-1)
            
            # 显示景深图
            self.display_original_image_custom(colored_depth)
            
            self.logger.info("景深图显示完成")
            
        except Exception as e:
            self.logger.error(f"显示景深图失败: {e}", exc_info=True)
    
    def on_original_canvas_resize(self: 'MainWindow', event):
        """原始图片画布大小改变事件处理（使用防抖）"""
        # 取消之前的定时器
        if self.resize_timer_original is not None:
            self.root.after_cancel(self.resize_timer_original)
        
        # 设置新的定时器，100ms后执行重绘
        self.resize_timer_original = self.root.after(100, self._redraw_original_canvas)
    
    def _redraw_original_canvas(self: 'MainWindow'):
        """重绘原始图片画布"""
        self.resize_timer_original = None
        
        if self.image is not None:
            # 根据开关状态决定显示什么（优先级：景深图 > 去背景图 > 原图）
            if self.use_depth_input and self.depth_map is not None:
                # 显示景深图
                self.display_depth_map()
            elif self.use_rembg and self.image_no_bg is not None:
                # 显示去背景图
                self.display_original_image_custom(self.image_no_bg)
            else:
                # 显示原始图片
                self.display_original_image()
            
            # 如果有选择的点或框，也需要重新绘制
            if self.selected_points or self.selected_box:
                # 使用历史管理器中的方法重绘标记
                self._redraw_selection_markers()
    
    def on_result_canvas_resize(self: 'MainWindow', event):
        """结果图片画布大小改变事件处理（使用防抖）"""
        # 取消之前的定时器
        if self.resize_timer_result is not None:
            self.root.after_cancel(self.resize_timer_result)
        
        # 设置新的定时器，100ms后执行重绘
        self.resize_timer_result = self.root.after(100, self._redraw_result_canvas)
    
    def _redraw_result_canvas(self: 'MainWindow'):
        """重绘结果图片画布"""
        self.resize_timer_result = None
        
        if self.current_result_image is not None:
            # 重新绘制结果图片
            self.display_image(self.current_result_image, self.result_canvas)

